// CadEngine.h
//
#ifndef CADENGINE_H
#define CADENGINE_H

#include "SnapEngine.h"
#include "CadSettings.h"

#include "OpenGL/Math.h"

#include <map>
#include <vector>


namespace OpenGL{
	class Renderer;
}

class CadTool;
class VObjectManager;
class VObject;

class CadEngine
{
	friend class CadTool;
public:
	typedef std::map<unsigned int,CadTool*> CadTools;

	enum CommandType{ Create, Destroy, Select, Move, Measure };
	enum PrimitiveType{ None, Point, Line, PolyLine, Triangle, Quad, Circle };
	
	struct Command
	{
		PrimitiveType                      primitive;
		OpenGL::Color                      color;
		CommandType                        command;
		std::vector< OpenGL::Math::dvec3 > points;
		std::string                        attributes;
		unsigned int                       target;
	};

private:
	double _worldSize;
	double _pixelSize;
	
	bool            _rubberband;
	CadTools        _tools;
	CadTool        *_currTool;
	VObjectManager *_objManager;
	SnapEngine      _snapEngine;
	CadSettings     _settings;
	
	std::vector<Command> _commands;
	std::vector<Command> _undo;

	void createGeometry( const Command &c );
	void selectGeometry( const Command &c );
	void destroyGeometry( const Command &c );
	
	//OpenGL::Math::dvec3 chooseSnapPoint( const OpenGL::Math::dvec3 &p );
	void setAttributes( VObject *obj, const Command &c );
	void setCurrentTool( CadTool *tool );
	CadTool *getCurrentTool() const;

public:
	CadEngine( VObjectManager *objManager );
	~CadEngine();

	void init();

	int addTool( CadTool *t );

	std::vector<unsigned int> getSelectedObjects() const;
	void hilightObject( const OpenGL::Math::dvec3 &p );
	void startRubberBand( const OpenGL::Math::dvec3 &p );
	void updateRubberBand( const OpenGL::Math::dvec3 &p );
	void endRubberBand( const OpenGL::Math::dvec3 &p );

	void updateSizes( double worldSize, double pixelSize );
	void issueCommand( const Command &c, bool queued = false );
	void executeCommands();
	void executeCommand( const Command &c );
	void draw( OpenGL::Renderer *r );

	void undo();
	void redo();

	void   enableTool( int toolID );
	bool   isEnabled()         const;
	double pixelSize()         const { return _pixelSize; }
	double worldSize()         const { return _worldSize; }
	CadTools tools()           const { return _tools; }
	CadTool  *tool(int toolID);
	CadSettings settings()     const { return _settings; }
};

#endif